package com.sneakxy.cloudbase.platform.controller;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.csource.common.MyException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sneakxy.cloudbase.platform.bean.UEditorSetting;
import com.sneakxy.cloudbase.platform.bean.UploadFile;
import com.sneakxy.cloudbase.platform.service.UploadFileClient;
import com.sneakxy.cloudbase.platform.utils.UEditorContants;
import com.sneakxy.cloudbase.platform.utils.web.DataGrid;
import com.sneakxy.cloudbase.platform.utils.web.PageSearch;
import com.sneakxy.cloudbase.platform.utils.web.Response;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;

@Api(tags="UEITOR富文本编辑器api")
@RestController
@RequestMapping("/api/editor/ueditor")
public class UEditorController extends BaseController {
	
	@Resource
	private UEditorSetting ueditorSetting;
	
	@Resource
	private JSONObject ueditorJsonConfig;
	
	@Autowired
	private UploadFileClient uploadFileClient;
	
	@ApiOperation("UEDITOR富文本编辑器配置")
	@RequiresAuthentication
	@GetMapping(params="action=config")
	public Object config(
			HttpServletRequest request, HttpServletResponse response,
			@ApiParam(name="callback", value="回调方法名")
			@RequestParam(name="callback", required=false)
			String callback) throws IOException {
		JSONObject json = (JSONObject) ueditorJsonConfig.clone();
		String imageUrlPrefix = ueditorSetting.getFullUrl(request, "/api/editor/ueditor/image/");
		String fileUrlPrefix = ueditorSetting.getFullUrl(request, "/api/editor/ueditor/file/");
		if(!json.containsKey("imageUrlPrefix")) {
			json.put("imageUrlPrefix", imageUrlPrefix);
		}
		if(!json.containsKey("imageManagerUrlPrefix")) {
			json.put("imageManagerUrlPrefix", imageUrlPrefix);
		}
		if(!json.containsKey("scrawlUrlPrefix")) {
			json.put("scrawlUrlPrefix", imageUrlPrefix);
		}
		if(!json.containsKey("snapscreenUrlPrefix")) {
			json.put("snapscreenUrlPrefix", imageUrlPrefix);
		}
		if(!json.containsKey("catcherUrlPrefix")) {
			json.put("catcherUrlPrefix", imageUrlPrefix);
		}
		if(!json.containsKey("videoUrlPrefix")) {
			json.put("videoUrlPrefix", ueditorSetting.getFullUrl(request, "/api/editor/ueditor/video/"));
		}
		if(!json.containsKey("fileUrlPrefix")) {
			json.put("fileUrlPrefix", fileUrlPrefix);
		}
		if(!json.containsKey("fileManagerUrlPrefix")) {
			json.put("fileManagerUrlPrefix", fileUrlPrefix);
		}
		return this.response(json, callback);
	}
	
	@ApiOperation("上传图片信息")
	@RequiresAuthentication
	@PostMapping(params="action=image")
	public Object image(
			@ApiParam(name="callback", value="回调方法名")
			@RequestParam(name="callback", required=false)
			String callback, MultipartFile file) throws IOException, MyException {
		return this.upload(callback, file, UEditorContants.FILE_TYPE_IMAGE);
	}
	
//	自带截图功能（snapscreen）无法传递登录信息，所以去掉了，不推荐使用
//	@RequestMapping(params="action=snapscreen")
//	public Object snapscreen(String callback, MultipartFile file) throws IOException, MyException {
//		FileItemStream fileStream = null;
//		FileItem fileItem = null;
//		String originFileName = null;
//		ServletFileUpload upload = multipartResolver.getServletFileUpload(request);
//		try {
//			FileItemIterator iterator = upload.getItemIterator(request);
//			FileItemFactory factory = upload.getFileItemFactory();
//			while (iterator.hasNext()) {
//				fileStream = iterator.next();
//				originFileName = fileStream.getName();
//				fileItem = factory.createItem(fileStream.getFieldName(), fileStream.getContentType(),
//						fileStream.isFormField(), originFileName);
//				if (!(fileStream.isFormField()))
//					break;
//				fileStream = null;
//				fileItem = null;
//			}
//			try {
//                Streams.copy(fileStream.openStream(), fileItem.getOutputStream(), true);
//            } catch (FileUploadIOException e) {
//                throw (FileUploadException) e.getCause();
//            } catch (IOException e) {
//                throw new IOFileUploadException(format("Processing of %s request failed. %s",
//                		FileUploadBase.MULTIPART_FORM_DATA, e.getMessage()), e);
//            }
//            final FileItemHeaders fih = fileStream.getHeaders();
//            fileItem.setHeaders(fih);
//            
//            UEditor ueditor = this.uEditorService.uploadAndSave(request, new CommonsMultipartFile(fileItem), UEditor.TYPE_IMAGE);
//            return this.response(response, ueditor.toMap(), callback);
//		} catch (FileUploadException e) {
//
//		} catch (IOException localIOException) {
//
//		}
//		return "{\r\n" + 
//				"    \"state\": \"SUCCESS\",\r\n" + 
//				"    \"url\": \"upload/demo.jpg\",\r\n" + 
//				"    \"title\": \"demo.jpg\",\r\n" + 
//				"    \"original\": \"demo.jpg\"\r\n" + 
//				"}";
//	}
	
	@RequiresAuthentication
	@ApiOperation("上传图片信息")
	@PostMapping(params="action=scrawl")
	public Object scrawl(
			HttpServletRequest request, HttpServletResponse response, 
			@ApiParam(name="callback", value="回调方法名")
			@RequestParam(name="callback", required=false)
			String callback, 
			@ApiParam(name="source", value="base64图片编码源", required=true)
			@RequestParam(name="source")
			String source) throws IOException, MyException {
		String filename = String.format("scrawl%s.jpg", DateFormatUtils.format(Calendar.getInstance(), "yyyyMMddHHmmss"));
		Response<UploadFile> res = uploadFileClient.base64(source, null, UploadFile.EXTENT_PUBLIC, UEditorContants.FILE_TYPE_IMAGE, filename);
		if(res.isSuccess()) {
			UploadFile uFile = res.getData();
			return this.response(toMap(uFile), callback);
		}
		return failed(callback);
	}
	
	@RequiresAuthentication
	@ApiOperation("次接口已经失效，图片搜索已经失效（百度不提供了），无法远程抓取图片")
	@PostMapping(params="action=catchimage")
	public Object catchimage(String callback, String[] source) throws IOException, MyException {
		throw new UnsupportedOperationException("图片搜索已经失效（百度不提供了），无法远程抓取图片");
	}
	
	@RequiresAuthentication
	@ApiOperation("上传视频信息")
	@PostMapping(params="action=video")
	public Object video(
			@ApiParam(name="callback", value="回调方法名")
			@RequestParam(name="callback", required=false)
			String callback, MultipartFile file) throws IOException, MyException {
		return this.upload(callback, file, UEditorContants.FILE_TYPE_VIDEO);
	}
	
	@RequiresAuthentication
	@ApiOperation("上传文件信息")
	@PostMapping(params="action=file")
	public Object file(
			@ApiParam(name="callback", value="回调方法名")
			@RequestParam(name="callback", required=false)
			String callback, MultipartFile file) throws IOException, MyException {
		return this.upload(callback, file, UEditorContants.FILE_TYPE_FILE);
	}
	
	@RequiresAuthentication
	@ApiOperation("图片列表信息")
	@GetMapping(params="action=listimage")
	public Object listimage(
			@ApiParam(name="start", value="开始记录数", required=true)
			@RequestParam(name="start")
			int start,
			@ApiParam(name="size", value="每页记录数", required=true)
			@RequestParam(name="size")
			int size,
			@ApiParam(name="callback", value="回调方法名")
			@RequestParam(name="callback", required=false)
			String callback) throws IOException, MyException {
		PageSearch<String> search = new PageSearch<String>();
		search.setPageNumber(start / size);
		search.setPageSize(size);
		Response<DataGrid<UploadFile>> datagrid = uploadFileClient.datagrid(search, UEditorContants.FILE_TYPE_IMAGE);
		Map<String, Object> result = toList(datagrid.getData(), start);
		return this.response(result, callback);
	}
	
	@RequiresAuthentication
	@ApiOperation("文件列表信息")
	@GetMapping(params="action=listfile")
	public Object listfile(
			@ApiParam(name="start", value="开始记录数", required=true)
			@RequestParam(name="start")
			int start,
			@ApiParam(name="size", value="每页记录数", required=true)
			@RequestParam(name="size")
			int size,
			@ApiParam(name="callback", value="回调方法名")
			@RequestParam(name="callback", required=false)
			String callback) throws IOException, MyException {
		PageSearch<String> search = new PageSearch<String>();
		search.setPageNumber(start / size + 1);
		search.setPageSize(size);
		Response<DataGrid<UploadFile>> datagrid = uploadFileClient.datagrid(search, UEditorContants.FILE_TYPE_FILE);
		Map<String, Object> result = toList(datagrid.getData(), start);
		return this.response(result, callback);
	}
	
	public Object upload(String callback, MultipartFile file, String filetype) {
		Response<UploadFile> res = uploadFileClient.upload(file, null, UploadFile.EXTENT_PUBLIC, filetype, null);
		if(res.isSuccess()) {
			UploadFile uFile = res.getData();
			return this.response(toMap(uFile), callback);
		}
		return failed(callback);
	}
	
	public Map<String, Object> toList(DataGrid<UploadFile> datagrid, int start) {
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		Iterator<UploadFile> it = datagrid.getRows().iterator();
		while(it.hasNext()) {
			list.add(this.toMap(it.next()));
		}
		Map<String, Object> result = new LinkedHashMap<String, Object>();
		result.put("state", "SUCCESS");
		result.put("list", list);
		result.put("start", start);
		result.put("total", datagrid.getTotal());
		return result;
	}

	public Object failed(String callback) {
		Map<String, Object> result = new LinkedHashMap<String, Object>();
		result.put("state", "FAILED");
		return this.response(result, callback);
	}
	
	public Map<String, Object> toMap(Map<String, Object> file) {
		Map<String, Object> result = new LinkedHashMap<String, Object>();
		result.put("state", "SUCCESS");
		result.put("url", file.get("id"));
		result.put("title", file.get("name"));
		result.put("original", file.get("name"));
		return result;
	}
	
	public Map<String, Object> toMap(UploadFile file) {
		Map<String, Object> result = new LinkedHashMap<String, Object>();
		result.put("state", "SUCCESS");
		result.put("url", file.getId());
		result.put("title", file.getName());
		result.put("original", file.getName());
		return result;
	}
	
	public Object response(Object obj, String callback) {
		if(StringUtils.isBlank(callback)) {
			return obj;
		}
		StringBuilder builder = new StringBuilder();
		builder.append(callback).append("(");
		builder.append(JSON.toJSONString(obj));
		builder.append(")");
		return builder.toString();
	}
	
}
